package main

import (
	"doubanRead/logger"
	"doubanRead/pie"
	"doubanRead/tools"
	"encoding/json"
	"fmt"
	"github.com/PuerkitoBio/goquery"
	"net/http"
	"regexp"
	"strings"
	"time"
)

// 清洗目录信息
func clearTocInfo(tocInfo string) (string, error) {
	var tocObject []Chapter
	err := json.Unmarshal([]byte(tocInfo), &tocObject)
	if err != nil {
		return "", err
	}
	var tocInfoStr string
	tmpLenth := len(tocObject)
	if len(tocObject) > 0 {

		for i, chapter := range tocObject {
			if (i + 1) == tmpLenth {
				tocInfoStr += string(chapter.Title)
			} else {
				tocInfoStr += string(chapter.Title) + "||"
			}
		}

		return tocInfoStr, nil
	}
	return "", nil
}

// 从URL提取书籍ID和类型
func extractBookInfo(url string) (string, string) {
	url, err := tools.GetWithRedirectTrace(url)
	if err != nil {
		fmt.Println(err)
		return "", ""
	}
	re := regexp.MustCompile(`/(ebook|column)/(\d+)`)
	match := re.FindStringSubmatch(url)
	if len(match) < 3 {
		return "", ""
	}
	return match[2], match[1]
}

// 获取出版书籍基本信息
func getEbookInfo(url, bookID string, logg logger.Logger) (*BookInfo, error) {
	doc, err := fetchDocument(url)
	if err != nil {
		return nil, err
	}

	info := &BookInfo{
		ID:   bookID,
		Type: "ebook",
	}

	// 提取标题
	info.Title = strings.TrimSpace(doc.Find("h1.article-title").Text())

	// 提取副标题
	info.Subtitle = strings.TrimSpace(doc.Find("p.subtitle").Text())

	// 提取封面
	if cover, exists := doc.Find(".cover img").First().Attr("src"); exists {
		// 移除所有尺寸后缀，获取原始封面
		newURL := regexp.MustCompile(`!\w+\.jpg$`).ReplaceAllString(cover, "")
		info.Cover = newURL
	}

	authorText := strings.TrimSpace(doc.Find("p:contains('作者') .labeled-text").Text())
	// 提取作者
	info.Authors = append(info.Authors, strings.TrimSpace(authorText))
	// 译者
	translatorText := strings.TrimSpace(doc.Find("p:contains('译者') .labeled-text").Text())
	info.Translator = strings.TrimSpace(translatorText)
	// 提取类别
	cate := strings.TrimSpace(doc.Find("p.category .labeled-text").Text())
	cate = strings.Replace(cate, " ", "", -1)
	info.Category = cate

	// 提取出版社和出版日期
	publisherText := strings.TrimSpace(doc.Find("p:contains('出版社') .labeled-text").Text())
	// 替换非标准空格和换行符，并标准化分隔符
	cleanedText := strings.ReplaceAll(publisherText, " ", " ") // 替换HTML空格实体
	cleanedText = strings.ReplaceAll(cleanedText, "\n", "")    // 移除换行
	cleanedText = strings.ReplaceAll(cleanedText, " / ", "/")  // 统一分隔符格式

	if cleanedText != "" {
		parts := strings.Split(cleanedText, "/")
		if len(parts) >= 2 {
			info.Publisher = strings.TrimSpace(parts[0])
			cleaned := strings.ReplaceAll(parts[1], " ", "") // 移除空格
			re := regexp.MustCompile(`\d{4}-\d{2}`)
			// 提取首个匹配项
			match := re.FindString(cleaned)
			if match != "" {
				info.PublishDate = strings.TrimSpace(match)
			} else {
				info.PublishDate = ""
			}
		} else {
			info.Publisher = publisherText
		}
	}

	// 提取提供方
	info.Provider = strings.TrimSpace(doc.Find("p:contains('提供方') .labeled-text").Text())

	// 提取字数
	word := strings.TrimSpace(doc.Find("p:contains('字数') .labeled-text").Text())
	word = strings.ReplaceAll(word, "约", "")
	word = strings.ReplaceAll(word, ",", "") // 注意，这里会删除所有的逗号，包括数字中的逗号
	word = strings.ReplaceAll(word, "字", "")
	word = strings.ReplaceAll(word, " ", "")
	info.WordCount = word

	// 提取ISBN
	info.ISBN = strings.TrimSpace(doc.Find("p:contains('ISBN') .labeled-text").Text())

	// 提取评分
	info.Rating = strings.TrimSpace(doc.Find(".article-ebook-rating .score").First().Text())

	sel := doc.Find(".original-price-count")
	if sel.Length() > 0 {
		// 提取价格
		tempPrice := strings.TrimSpace(sel.First().Text())
		info.Price, _ = extractFirstPrice(tempPrice)
	} else {
		tempPrice := strings.TrimSpace(doc.Find(".current-price-count").First().Text())
		info.Price, _ = extractFirstPrice(tempPrice)
	}

	// 提取豆瓣评分
	info.DoubanScore = strings.TrimSpace(doc.Find("#douban-book-rating-root a").Text())

	// 提取描述
	info.Description = extractEbookDescription(doc)

	return info, nil
}

func extractFirstPrice(s string) (string, error) {
	priceRegex := regexp.MustCompile(`[-+]?\d*\.?\d+|\d+`)
	match := priceRegex.FindString(s)
	if match == "" {
		return "", fmt.Errorf("未找到有效价格")
	}
	return match, nil
}

// 获取电子书籍基本信息
func getColumnInfo(url, bookID string) (*BookInfo, error) {
	doc, err := fetchDocument(url)
	if err != nil {
		return nil, err
	}

	info := &BookInfo{
		ID:   bookID,
		Type: "column",
	}

	// 提取标题 - 使用更精确的选择器
	titleSelection := doc.Find("h1.title-wrapper .title")
	titleSelection.Find("label").Remove() // 移除可能存在的标签
	info.Title = strings.TrimSpace(titleSelection.Text())

	// 提取副标题
	info.Subtitle = strings.TrimSpace(doc.Find(".highlight.author-highlight").Text())

	// 提取封面 - 优先使用Open Graph图像
	if cover, exists := doc.Find(`meta[property="og:image"]`).Attr("content"); exists {
		// 移除所有尺寸后缀，获取原始封面
		newURL := regexp.MustCompile(`!\w+\.jpg$`).ReplaceAllString(cover, "")
		info.Cover = newURL
	} else if cover, exists := doc.Find(".article-cover img").Attr("src"); exists {
		info.Cover = cover
	} else if cover, exists := doc.Find(".avatar img").Attr("src"); exists {
		// 备用封面选择器
		info.Cover = cover
	}

	// 提取作者
	authorName := strings.TrimSpace(doc.Find(".author .name").Text())
	if authorName != "" {
		info.Authors = []string{authorName}
	}

	// 提取字数
	word := strings.TrimSpace(doc.Find(".count.word-count .text").Text())
	word = strings.ReplaceAll(word, ",", "")
	info.WordCount = word

	// 提取阅读数
	readCount := strings.TrimSpace(doc.Find(".count.read-count .text").Text())
	readCount = strings.ReplaceAll(readCount, ",", "")
	info.ReadCount = readCount

	// 提取加入书架数
	libraryCount := strings.TrimSpace(doc.Find(".count.in-library-count .text").Text())
	libraryCount = strings.ReplaceAll(libraryCount, ",", "")
	info.InLibraryCount = libraryCount

	// 提取推荐票数
	recommendCount := strings.TrimSpace(doc.Find(".count.rec-vote-count .text").Text())
	recommendCount = strings.ReplaceAll(recommendCount, ",", "")
	info.RecommendCount = recommendCount

	// 提取评分
	info.Rating = strings.TrimSpace(doc.Find(".rating-light .score").Text())

	// 提取类别
	category := doc.Find(".categories a.tag").First().Text()
	if category != "" {
		info.Category = category
	}

	// 提取标签
	doc.Find(".tags a.tag").Each(func(_ int, s *goquery.Selection) {
		tag := strings.TrimSpace(s.Text())
		if tag != "" && !strings.Contains(s.AttrOr("class", ""), "btn-toggler") {
			info.Tags = append(info.Tags, tag)
		}
	})

	// 提取描述
	info.Description = extractColumnDescription(doc)
	return info, nil
}

// 提取出版书籍描述
func extractEbookDescription(doc *goquery.Document) string {
	// 查找带有itemprop="description"的div
	descriptionDiv := doc.Find(`div[itemprop="description"]`)
	if descriptionDiv.Length() == 0 {
		return ""
	}

	// 提取所有段落文本
	var paragraphs []string
	descriptionDiv.Find("p").Each(func(_ int, s *goquery.Selection) {
		text := strings.TrimSpace(s.Text())
		if text != "" {
			paragraphs = append(paragraphs, text)
		}
	})

	// 合并段落为单个字符串
	return strings.Join(paragraphs, "\n\n")
}

// 提取电子书籍描述
func extractColumnDescription(doc *goquery.Document) string {
	// 优先提取展开的简介
	description := ""
	doc.Find(`div[itemprop="description"] .when-expand`).Each(func(_ int, s *goquery.Selection) {
		var paragraphs []string
		s.Find("p").Each(func(_ int, p *goquery.Selection) {
			text := strings.TrimSpace(p.Text())
			if text != "" {
				paragraphs = append(paragraphs, text)
			}
		})
		if len(paragraphs) > 0 {
			description = strings.Join(paragraphs, "\n\n")
		}
	})

	// 如果没有展开的简介，尝试折叠的简介
	if description == "" {
		doc.Find(`div[itemprop="description"] .when-fold`).Each(func(_ int, s *goquery.Selection) {
			text := strings.TrimSpace(s.Text())
			// 移除末尾的"..."和展开按钮文本
			if idx := strings.Index(text, "…"); idx != -1 {
				text = text[:idx]
			}
			description = text
		})
	}

	return description
}

// 获取出版书籍目录
func getEbookToc(url, bookID string) (*TocInfo, error) {
	doc, err := fetchDocument(url)
	if err != nil {
		return nil, err
	}

	toc := &TocInfo{
		BookID:   bookID,
		BookType: "ebook",
	}

	// 提取目录 - 使用更精确的选择器
	doc.Find(".table-of-contents ol li h5.story-title a").Each(func(_ int, s *goquery.Selection) {
		title := strings.TrimSpace(s.Text())
		title = strings.ReplaceAll(title, " ", "")
		if title != "" {
			if href, exists := s.Attr("href"); exists {
				toc.Chapters = append(toc.Chapters, Chapter{

					Title: title,
					URL:   href, // 已经是完整URL
				})
			} else {
				toc.Chapters = append(toc.Chapters, Chapter{Title: title})
			}
		}
	})

	// 如果上面的选择器找不到目录，尝试备用选择器
	if len(toc.Chapters) == 0 {
		doc.Find("ul.toc-list li a").Each(func(_ int, s *goquery.Selection) {
			title := strings.TrimSpace(s.Text())
			if title != "" {
				if href, exists := s.Attr("href"); exists {
					toc.Chapters = append(toc.Chapters, Chapter{
						Title: title,
						URL:   "https://read.douban.com" + href,
					})
				} else {
					toc.Chapters = append(toc.Chapters, Chapter{Title: title})
				}
			}
		})
	}

	return toc, nil
}

// 获取电子书籍目录
func getColumnToc(bookID string) (*TocInfo, error) {
	// 第一步：获取章节总数
	total, err := getColumnChaptersTotal(bookID)
	if err != nil {
		return nil, err
	}

	toc := &TocInfo{
		BookID:   bookID,
		BookType: "column",
	}

	// 第二步：根据总数获取所有章节
	if total <= 100 {
		// 一次获取所有章节
		chapters, err := fetchColumnChapters(bookID, 0, total)
		if err != nil {
			return nil, err
		}
		toc.Chapters = chapters
	} else {
		// 分批次获取章节
		for start := 0; start < total; start += 100 {
			limit := 100
			if start+limit > total {
				limit = total - start
			}

			chapters, err := fetchColumnChapters(bookID, start, limit)
			if err != nil {
				return nil, err
			}
			toc.Chapters = append(toc.Chapters, chapters...)
		}
	}

	return toc, nil
}

// 获取电子书籍章节总数
func getColumnChaptersTotal(bookID string) (int, error) {
	// 获取总数
	resp, err := fetchColumnChaptersAPI(bookID, 0, 1)
	if err != nil {
		return 0, err
	}

	return resp.Total, nil
}

// 获取电子书籍章节
func fetchColumnChapters(bookID string, start, limit int) ([]Chapter, error) {
	resp, err := fetchColumnChaptersAPI(bookID, start, limit)
	if err != nil {
		return nil, err
	}

	var chapters []Chapter
	for _, item := range resp.List {
		// 构建章节URL
		chapterURL := fmt.Sprintf("https://read.douban.com/reader/column/%s/chapter/%s/", bookID, item.ID)
		chapters = append(chapters, Chapter{
			Title: item.Title,
			URL:   chapterURL,
		})
	}

	return chapters, nil
}

// 调用API获取章节数据
func fetchColumnChaptersAPI(bookID string, start, limit int) (*ColumnChaptersResponse, error) {
	apiURL := fmt.Sprintf("https://read.douban.com/j/column_v2/%s/chapters?start=%d&limit=%d&latestFirst=0", bookID, start, limit)

	client := &http.Client{Timeout: 15 * time.Second}
	req, err := http.NewRequest("GET", apiURL, nil)
	if err != nil {
		return nil, err
	}

	// 设置请求头
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Referer", fmt.Sprintf("https://read.douban.com/column/%s/", bookID))

	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("API请求失败: %s (状态码: %d)", resp.Status, resp.StatusCode)
	}

	// 解析JSON响应
	var apiResp ColumnChaptersResponse
	if err := json.NewDecoder(resp.Body).Decode(&apiResp); err != nil {
		return nil, fmt.Errorf("JSON解析失败: %v", err)
	}

	return &apiResp, nil
}

// 获取并解析HTML文档
func fetchDocument(url string) (*goquery.Document, error) {
	client := &http.Client{
		Timeout: 15 * time.Second,
	}

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}

	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
	req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
	req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
	req.Header.Set("Referer", "https://read.douban.com/")

	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("HTTP错误: %s (状态码: %d)", resp.Status, resp.StatusCode)
	}

	return goquery.NewDocumentFromReader(resp.Body)
}

// 保存JSON文件
func saveJSON(logg logger.Logger, cache *pie.FileCache, filename string, data interface{}) {
	jsonData, err := json.MarshalIndent(data, "", "  ")
	if err != nil {
		logg.Infof("JSON编码失败: %v\n", err)
		return
	}

	//if err := ioutil.WriteFile(filename, jsonData, 0644); err != nil {
	//	logg.Infof("文件保存失败: %v\n", err)
	//} else {
	//	logg.Infof("已保存: %s\n", filename)
	//}

	if err := cache.Set(filename, jsonData); err != nil {
		logg.Infof("Failed to set cache: %v\n", err)
	}

}
